package game.web.dao.impl;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;

import projectx.core.dao.impl.PreparedStatementBuilder;
import projectx.core.dao.impl.StatementBuilder;

public class SqlLoader {

	public static final String MSG_IO_EXCEPTION = "MSG_IO_EXCEPTION";

	public static final String MSG_ILLEGAL_STATEMENT_TYPE = "MSG_ILLEGAL_STATEMENT_TYPE";

	public static final String MSG_PARSE_FAIL = "MSG_PARSE_FAIL";

	public static final String ILLEGAL_SQLID = "ILLEGAL_SQLID";

	public static final String FILE_NOT_FOUND_EXCEPTION = "FILE_NOT_FOUND_EXCEPTION";

	private static final char CHAR_PERIOD = '.';

	private static final String TYPE_STATEMENT = "ST";

	private static final String TYPE_PREPAREDSTATEMENT = "PS";

	private static final String DEF_FILENAME = "sql.prop";

	private static String filename = null;

	private static Map builders = null;

	public static void setFilename(String filename) {
		SqlLoader.filename = filename;
	}

	public static synchronized void initialize() {
		builders = new HashMap() {
			public Object get(Object key) {
				Object value = super.get(key);
				if (value == null) {
					MessageFormat format = new MessageFormat(ILLEGAL_SQLID);
					throw new IllegalArgumentException(format
							.format(new Object[] { key }));
				}
				return value;
			}
		};
		Properties data = new Properties();
		InputStream is = null;
		try {
			if (filename == null) {
				is = SqlLoader.class.getResourceAsStream(DEF_FILENAME);

				filename = DEF_FILENAME;
			} else {
				is = new FileInputStream(filename);
			}
			if (is == null) {
				MessageFormat format = new MessageFormat(
						FILE_NOT_FOUND_EXCEPTION);
				throw new IllegalArgumentException(format
						.format(new Object[] { filename }));
			}
			data.load(is);

		} catch (IOException e) {
			MessageFormat format = new MessageFormat(MSG_IO_EXCEPTION);
			IllegalStateException ise = new IllegalStateException(format
					.format(new Object[] { filename, e }));
			ise.initCause(e);
			throw ise;
		} finally {
			if (null != is) {
				try {
					is.close();
				} catch (IOException e) {
					MessageFormat format = new MessageFormat(MSG_IO_EXCEPTION);
					IllegalStateException ise = new IllegalStateException(
							format.format(new Object[] { filename, e }));
					ise.initCause(e);
					throw ise;
				}
			}
		}

		Iterator it = data.entrySet().iterator();
		Map.Entry entry;
		String key;
		String value;
		String sqlId = null;
		String stmtType = null;
		int index;
		try {
			while (it.hasNext()) {
				entry = (Map.Entry) it.next();
				key = (String) entry.getKey();
				value = (String) entry.getValue();
				index = key.indexOf(CHAR_PERIOD);
				if (index == -1) {
					sqlId = key;
				} else {
					sqlId = key.substring(0, index);
					stmtType = key.substring(index + 1);
				}

				if (stmtType == null || stmtType.length() == 0) {
					builders.put(sqlId, new PreparedStatementBuilder(value));
				} else if (TYPE_STATEMENT.equals(stmtType)) {
					builders.put(sqlId, new StatementBuilder(value));
				} else if (TYPE_PREPAREDSTATEMENT.equals(stmtType)) {
					builders.put(sqlId, new PreparedStatementBuilder(value));
				} else {
					MessageFormat format = new MessageFormat(
							MSG_ILLEGAL_STATEMENT_TYPE);
					throw new IllegalArgumentException(format
							.format(new Object[] { stmtType }));
				}
			}
		} catch (IllegalArgumentException e) {
			MessageFormat format = new MessageFormat(MSG_PARSE_FAIL);
			IllegalArgumentException iae = new IllegalArgumentException(format
					.format(new Object[] { sqlId }));
			iae.initCause(e);
			throw iae;
		}
	}

	public static synchronized Map getBuilders() throws IllegalStateException,
			IllegalArgumentException {
		if (builders != null) {
			return builders;
		}
		initialize();
		return builders;
	}
}